package variabilitysmelldetection.analyses;

import java.util.ArrayList;
import java.util.List;

import variabilitysmelldetection.measurement.measures.Measure;
import variabilitysmelldetection.measurement.measures.component.CouplingBetweenObjects;
import variabilitysmelldetection.measurement.measures.component.NumberOfAttributes;
import variabilitysmelldetection.measurement.measures.component.NumberOfConstantRefinements;
import variabilitysmelldetection.measurement.measures.component.NumberOfMethods;
import variabilitysmelldetection.measurement.models.ComponentItem;
import variabilitysmelldetection.measurement.models.Project;
import variabilitysmelldetection.plugin.Activator;
import variabilitysmelldetection.plugin.preferences.PreferenceConstants;


public class ShotgunSurgery {
	private double noaThreshold;
	private double ncrThreshold;
	private double nooThreshold;
	private double cboThreshold;
	private String strategy;

	public ShotgunSurgery(){
		noaThreshold = Activator.getDefault().getPreferenceStore().getDouble(PreferenceConstants.SHOTGUNSURGERY_NOA_THRESHOLD);//3.1;   // high
		ncrThreshold = Activator.getDefault().getPreferenceStore().getDouble(PreferenceConstants.SHOTGUNSURGERY_NCR_THRESHOLD);//4.41;  // high
		nooThreshold = Activator.getDefault().getPreferenceStore().getDouble(PreferenceConstants.SHOTGUNSURGERY_NOO_THRESHOLD);//5.34;  // high
		cboThreshold = Activator.getDefault().getPreferenceStore().getDouble(PreferenceConstants.SHOTGUNSURGERY_CBO_THRESHOLD);//2.97;  // low
		strategy = "(NCR > "+ncrThreshold+") AND "
                + "(NOA > "+noaThreshold+") AND "
                + "(CBO > "+cboThreshold+") AND "
                + "(NOO > "+nooThreshold+")";
	}
	public String getStrategy(){
		return strategy;
	}
	
	public boolean hasShotgunSurgery(ComponentItem classe){
		double numOverrides = calculateRefinements(classe);
		double noa          = calculateNOA(classe);
		double noo          = calculateNOO(classe);
		double cbo          = calculateCBO(classe);
		return ((numOverrides > ncrThreshold) &&
				(noa > noaThreshold) &&
				(noo > nooThreshold) &&
				(cbo > cboThreshold));
	}
	
	public List<ComponentItem> getShotgunSurgeryClasses(Project project){
		List<ComponentItem> shotgunSurgeryClasses = new ArrayList<ComponentItem>();
		
		for (ComponentItem classe : project.getClassItems()) {
			if (hasShotgunSurgery(classe)) {
				shotgunSurgeryClasses.add(classe);
			}
		}
		return shotgunSurgeryClasses;
	}
	
	private double calculateRefinements(ComponentItem classe){
		double value = 0d;
		Measure nrt = classe.getMeasure(NumberOfConstantRefinements.class);
		if (nrt != null) {
			value = nrt.getValue();
		}
		
		return value;
	}
	
	private double calculateNOA(ComponentItem classe){
		double value = 0d;
		Measure noa = classe.getMeasure(NumberOfAttributes.class);
		if (noa != null) {
			value = noa.getValue();
		}
		
		return value;
	}
	
	private double calculateNOO(ComponentItem classe){
		double value = 0d;
		Measure noo  = classe.getMeasure(NumberOfMethods.class);
		if (noo != null) {
			value = noo.getValue();
		}
		
		return value;
	}
	
	private double calculateCBO(ComponentItem classe){
		double value = 0d;
		Measure cbo  = classe.getMeasure(CouplingBetweenObjects.class);
		if (cbo != null) {
			value = cbo.getValue();
		}
		
		return value;
	}
}
